# -*- coding: UTF-8 -*-

"""
@Project: qingdeng_create_project
@Author: yewei
@Date: 2021-06-18
@Description: 用于创建通用型项目脚手架
"""

import re
import argparse
from pathlib import Path
from datetime import datetime


class CreateProject():
    __version__ = "1.0.0"

    def __init__(self):
        self._root_dir = ""
        self.file_docstring = ""
        self.today = datetime.today().strftime("%Y-%m-%d")
        self.company = "Hangzhou Qingdeng Network Tchnology Co.,Ltd."

    def version(self):
        "返回版本号"
        print(self.__version__)

    def create(self, username: str, project_name: str, project_path: str):
        """
        开启创建Python项目
            :param username: 用户名
            :param project_name: 项目名
            :param project_path: 项目地址
        :return: 创建结果
        """
        self.project_name = project_name
        self.file_docstring = f'# -*- coding: UTF-8 -*-\n"""\n@Project: {project_name}\n@Author: {username}\n@Date: {self.today}\n@Copyright:{self.company}\n'
        self._create_root_folder(project_path, project_name)
        self._create_child_folder()
        self._create_child_files()
        self._create_predefined_files()
        self._create_requirements_files()

    def _create_root_folder(self, project_path:str, project_name: str):
        """
        创建根目录
            :param project_path:用户设定的项目路径
            :param project_name: 项目名
        """
        self.store_dir = Path(__file__).parent
        workspace = Path(project_path)
        project_path = workspace if workspace.drive else Path(f"{Path.cwd()}/{project_path}")
        if not project_path.is_dir():
            print("用户指定路径为文件，将使用父级目录创建项目！")
            _root = project_path.parent
        else:
            _root = project_path
        self._root_dir = _root.joinpath(project_name)
        self._root_dir.mkdir(parents=True, exist_ok=True)

    def _create_child_folder(self):
        """
        创建子目录
        """
        for x in [
            "logs",          # 日志目录
            "static",        # 外放的静态文件目录
            "store",         # 项目内部使用的静态文件目录
            "utils",         # 项目内部公共方法目录
            "models",        # 数据库ORM配置目录
            "views",         # 项目视图目录
            "settings",      # 项目配置文件
            "schemas",       # 请求参数模式
            "routers",       # 项目接口路由配置目录
            "dependencies",  # Fastapi 依赖注入文件
            "tasks",         # Fastapi 后台任务文件
        ]:
            folder = self._root_dir.joinpath(x)
            print("正在生成目录：", folder)
            folder.mkdir(parents=True, exist_ok=True)

    def _create_child_files(self):
        """
        创建目录下初始化文件
        """
        for x, y in {
            "utils": "项目内部公共方法",
            "views": "项目接口视图",
            "schemas": "请求参数Schema配置模块",
            "dependencies": "依赖注入模块",
            "tasks": "后台运行任务模块",
        }.items():
            init_file = self._root_dir.joinpath(f"{x}/__init__.py")
            with open(init_file, "w", encoding="utf-8") as fw:
                print("正在生成文件：", init_file)
                fw.write(f'{self.file_docstring}@Description:{y}\n"""\n')
        with open(self._root_dir.joinpath("settings/public.py"), "w", encoding="utf-8") as fw:
            print("正在生成文件：", self._root_dir.joinpath("settings/public.py"))
            fw.write(f'{self.file_docstring}@Description:参数配置文件\n"""\n')

        self.env_name = re.sub(r"\W", "", self.project_name)
        with open(self._root_dir.joinpath("store/.env"), "w", encoding="utf-8") as fw:
            print("正在生成文件：", self._root_dir.joinpath("store/.env"))
            fw.write(f'{self.env_name}=dev')

    def _create_predefined_files(self):
        """
        预定义文件的初始化
        """
        for filename, x in {
            "models.py": ["models", ["__init__.py", ], ["数据库ORM配置"]],
            "setting.py": ["settings", ["__init__.py",], ["项目配置模块"]],
            "log.py": ["settings", ["log.py"], ["日志文件配置"]],
            "docs_tags.py": ["settings", ["docs_tags.py"], ["项目API文档配置"]],
            "config.py": ["settings", ["product_config.py", "test_config.py"], ["生产环境配置文件", "测试环境配置文件"]],
            "response.py": ["schemas", ["response.py"], ["环境配置文件"]],
            "app.py": [".", ["app.py"], ["项目启动APP配置"]],
            "routers.py": ["routers", ["__init__.py"], ["项目接口路由配置"]],
            "token.py": ["dependencies", ["token.py"], ["请求token相关配置"]],
            "headers.py": ["dependencies", ["headers.py"], ["处理请求头部信息"]],
            "common.py": ["utils", ["common.py"], ["项目内部通用方法类"]],
            "redis.py": ["utils", ["redis.py"], ["Redis缓存服务器配置类"]],
        }.items():
            with open(f"{self.store_dir}/{filename}", "r", encoding="utf-8") as fr:
                content = fr.read()

            if filename == "app.py":
                content = content.replace("FASTAPI-DOCS-TITLE", self.project_name)
                content = content.replace("FASTAPI-DOCS-DESCRIPTION", self.project_name)
            elif filename == "setting.py":
                content = content.replace("PY_SERVER", self.env_name)

            for y,z in enumerate(x[1]):
                with open(self._root_dir.joinpath(f"{x[0]}/{z}"), "w", encoding="utf-8") as fw:
                    print("正在生成文件：",self._root_dir.joinpath(f"{x[0]}/{z}"), x[2][y])
                    fw.write(f'{self.file_docstring}@Description:{x[2][y]}\n"""\n')
                    fw.write(content)

    def _create_requirements_files(self):
        """
        python依赖包配置文件
        """
        with open(f"{self.store_dir}/requirements.txt", "r", encoding="utf-8") as fr:
            content = fr.read()

        with open(self._root_dir.joinpath("requirements.txt"), "w", encoding="utf-8") as fw:
            fw.write(content)


def usage():
    print(
        """
        参数说明:
            -h or --help：显示帮助信息
            -n or --name：项目名称,必须参数
            -u or --username：创建人名称,必须参数
            -p or --path：项目存储地址,默认当前目录
            -v or --version：版本号
        """
    )


def start(args: argparse.Namespace):
    "启动参数解析"
    if args.project_name:
        CreateProject().create(args.username, args.project_name, args.project_path)
    elif args.version:
        CreateProject().version()
    else:
        usage()


if __name__ == '__main__':
    parser = argparse.ArgumentParser(usage="正在创建公司内部通用Python Fastapi项目......", description='创建公司内部通用Python Fastapi项目')
    parser.add_argument("-n", "--name", action="store", type=str, dest="project_name", help="项目名称")
    parser.add_argument("-u", "--username", action="store", type=str, dest="username", default=" ", help="创建人名称")
    parser.add_argument("-p", "--path", action="store", type=str, dest="project_path", default=f"{Path.cwd()}", help="项目存储地址")
    parser.add_argument("-v", "--version", action="count", dest="version", help="版本号")
    args = parser.parse_args()
    start(args)

    # CreateProject().create(" ", "new-pidan-for-fastapi", "D:/work/new-pidan-for-fastapi")
